/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "stub.h"
#include "secodeFuzz.h"
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "gmock/gmock-actions.h"
#include "HetroBackupJob.h"
#include "ScanMgr.h"

using ::testing::_;
using testing::AllOf;
using ::testing::AnyNumber;
using ::testing::AtLeast;
using testing::ByMove;
using testing::DoAll;
using ::testing::Eq;
using ::testing::Field;
using ::testing::Ge;
using ::testing::Gt;
using testing::InitGoogleMock;
using ::testing::Invoke;
using ::testing::Ne;
using ::testing::Return;
using ::testing::Sequence;
using ::testing::SetArgReferee;
using ::testing::SetArgumentPointee;
using ::testing::Throw;
using namespace std;

namespace {
    constexpr int NAS_SCANNER_THREAD_CNT = 32;
    constexpr int NAS_BACKUP_THREAD_CNT = 32;
}

class ScanTest : public Scanner {
public:
    explicit ScanTest(const ScanConfig& scanConfig);
    ~ScanTest() {};

    SCANNER_STATUS Start() override;
    SCANNER_STATUS Abort()override;
    SCANNER_STATUS Destroy() override;
    SCANNER_STATUS Enqueue(const std::string& directory, const std::string& prefix = "", uint8_t filterFlag = 0) override;
    SCANNER_STATUS EnqueueV2(const std::string& directory) override;
    SCANNER_STATUS GetStatus() override;
    ScanStatistics GetStatistics() override;

protected:
    ScanConfig m_config;
};

ScanTest::ScanTest(const ScanConfig& scanConfig) : Scanner(scanConfig) {}
SCANNER_STATUS ScanTest::Start() {
    return SCANNER_STATUS::SUCCESS;
}
SCANNER_STATUS ScanTest::Abort() {
    return SCANNER_STATUS::SUCCESS;
}
SCANNER_STATUS ScanTest::Destroy() {
    return SCANNER_STATUS::SUCCESS;
}
SCANNER_STATUS ScanTest::Enqueue(const std::string& directory, const std::string& prefix, uint8_t filterFlag) {
    return SCANNER_STATUS::SUCCESS;
}
SCANNER_STATUS ScanTest::EnqueueV2(const std::string& directory) {
    return SCANNER_STATUS::SUCCESS;
}
SCANNER_STATUS ScanTest::GetStatus() {
    return SCANNER_STATUS::COMPLETED;
}
ScanStatistics ScanTest::GetStatistics() {
    ScanStatistics scanStatistics;
    return scanStatistics;
}

static unique_ptr<Scanner> CreateScanInst_Stub (void* obj, ScanConfig scanConfig) {
    ScanConfig xx{};
    xx.maxCommonServiceInstance = 1;
    xx.scanCtrlMaxDataSize = "10737418240";
    xx.scanCtrlMinDataSize = "5368709120";
    xx.scanCtrlFileTimeSec = 30;
    xx.generatorIsFull = false;
    xx.scanCtrlMaxEntriesFullBkup = 100000;
    xx.scanCtrlMaxEntriesIncBkup = 50000;
    xx.scanCtrlMinEntriesFullBkup = 50000;
    xx.scanCtrlMinEntriesIncBkup = 25000;
    xx.scanMetaFileSize = 1048576000;
    xx.scanCheckPointEnable = 1;
    return make_unique<ScanTest>(xx);
}

class FuzzHetroBackup : public testing::Test {
public:
    void SetUp();
    void TearDown();
    void SetUpGenSubJobInfo();
    void TearDownGenSubJobInfo();
    void SetUpExecSubJobInfo();
    void TearDownExecSubJobInfo();
    static void SetUpTestCase();
    static void TearDownTestCase();
    std::unique_ptr<HetroBackupJob> m_hetroBackupJobObj;
    Stub stub;
};

static AppProtect::BackupJob BackupJobSetup()
{
    AppProtect::BackupJob backupJob;
    backupJob.requestId = "reqId123";
    backupJob.jobId = "jId123";
    backupJob.jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    backupJob.jobParam.dataLayout.extendInfo = "xxx";
    string filterString;
    AppProtect::ResourceFilter fileFilter;
    fileFilter.filterBy = "Name";
    fileFilter.type = "File";
    fileFilter.mode = "INCLUDE";
    fileFilter.rule = "Fuzzy";
    filterString = "/a";
    fileFilter.values.push_back(filterString);
    AppProtect::ResourceFilter dirFilter;
    dirFilter.filterBy = "Name";
    dirFilter.type = "Dir";
    dirFilter.mode = "INCLUDE";
    dirFilter.rule = "Fuzzy";
    filterString = "/b";
    dirFilter.values.push_back(filterString);
    AppProtect::ResourceFilter formatFilter;
    formatFilter.filterBy = "Format";
    formatFilter.type = "File";
    formatFilter.mode = "INCLUDE";
    formatFilter.rule = "Exact";
    filterString = "1";
    formatFilter.values.push_back(filterString);
    filterString = "2";
    formatFilter.values.push_back(filterString);
    filterString = "3";
    formatFilter.values.push_back(filterString);
    filterString = "4";
    formatFilter.values.push_back(filterString);
    filterString = "5";
    formatFilter.values.push_back(filterString);
    filterString = "6";
    formatFilter.values.push_back(filterString);
    AppProtect::ResourceFilter dateFilter;
    dateFilter.filterBy = "ModifyTime";
    dateFilter.type = "File";
    dateFilter.mode = "INCLUDE";
    dateFilter.rule = "Exact";
    filterString = "1641839400533";
    dateFilter.values.push_back(filterString);
    filterString = "1641943800694";
    dateFilter.values.push_back(filterString);
    backupJob.jobParam.filters.push_back(fileFilter);
    backupJob.jobParam.filters.push_back(dirFilter);
    backupJob.jobParam.filters.push_back(formatFilter);
    backupJob.jobParam.filters.push_back(dateFilter);
    backupJob.jobParam.advanceParams = "{\"small_file_aggregation\":\"0\",\"aggregate_level\":\"0\","
                                       "\"permissions_and_attributes\":\"1\"}";
    backupJob.protectEnv.id = "peId123";
    backupJob.protectEnv.name = "poName123";
    backupJob.protectEnv.type = "Vendor";
    backupJob.protectEnv.subType = "StorageOthers";
    backupJob.protectEnv.endpoint = "10.28.12.144";
    backupJob.protectEnv.port = 8080;
    backupJob.protectEnv.auth.extendInfo = "{\"fingerPrint\" : \"4928EBB6E58A3A395BC89317DD55B82F1B8C10E7\"}";
    backupJob.protectEnv.extendInfo = "{\"snapConsistency\":\"0\",\"verifyStatus\":\"1\",\"wwn\":\"\"}";
    backupJob.protectObject.id = "poID123";
    backupJob.protectObject.type = "storage";
    backupJob.protectObject.subType = "NasShare";
    backupJob.protectObject.name = "OceanstorFS";
    backupJob.protectObject.auth.authType = AuthType::NO_AUTHENTICATION;
    backupJob.protectObject.auth.authkey = "";
    backupJob.protectObject.auth.authPwd = "";
    backupJob.protectObject.extendInfo = "{\"authMode\":\"1\",\"filters\":\"\",\"ip\":\"10.28.12.144\""
                                         ",\"kerberosId\":\"0\",\"shareMode\":\"1\"}";
    string path = "/MetaFS/cache";
    HostAddress hostadd;
    hostadd.ip="10.28.12.144";
    StorageRepository cacheRepo;
    cacheRepo.repositoryType = RepositoryDataType::CACHE_REPOSITORY;
    cacheRepo.path.push_back(path);
    cacheRepo.remotePath = "/MetaFS/cache";
    cacheRepo.remoteHost.push_back(hostadd);
    cacheRepo.auth.authkey = "admin";
    cacheRepo.auth.authPwd = "Admin@123";
    cacheRepo.endpoint.ip = "10.28.12.144";
    cacheRepo.endpoint.port = 8088;
    StorageRepository dataRepo;
    dataRepo.repositoryType = RepositoryDataType::DATA_REPOSITORY;
    dataRepo.remotePath = "/BackupFS";
    dataRepo.path.push_back(dataRepo.remotePath);
    dataRepo.remoteHost.push_back(hostadd);
    dataRepo.auth.authkey = "admin";
    dataRepo.auth.authPwd = "Admin@123";
    dataRepo.endpoint.ip = "10.28.12.144";
    dataRepo.endpoint.port = 8088;
    StorageRepository metaRepo;
    metaRepo.repositoryType = RepositoryDataType::META_REPOSITORY;
    path = "/MetaFS/meta";
    metaRepo.path.push_back(path);
    metaRepo.remotePath = "/MetaFS/meta";
    metaRepo.remoteHost.push_back(hostadd);
    metaRepo.auth.authkey = "admin";
    metaRepo.auth.authPwd = "Admin@123";
    metaRepo.endpoint.ip = "10.28.12.144";
    metaRepo.endpoint.port = 8088;
    backupJob.repositories.push_back(cacheRepo);
    backupJob.repositories.push_back(dataRepo);
    backupJob.repositories.push_back(metaRepo);
    backupJob.extendInfo = "{\"auto_index\":\"false\",\"permissions_and_attributes\":\"0\",\"proxy_host_mode\":\"0\","
                           "\"small_file_aggregation\":\"0\"}";
    return backupJob;
}

static bool ReportJobDetails_Stub_SUC(void *ob, SubJobDetails& jobInfo)
{
    return true;
}

static bool ReportJobDetails_Stub_FAIL(void *ob, SubJobDetails& jobInfo)
{
    return false;
}

static bool ReadBackupCopyFromFile_Stub_SUC(void *ob, std::string backupCopyPathFullPath, HetroLastCopyDetails &backupCopy)
{
    return true;
}

static void CheckCertThumbPrint_Stub_SUC(ActionResult& returnValue, const std::string& ip, const int32_t port, const std::string& thumbPrint)
{
    returnValue.code = MP_SUCCESS;
    return;
}

static bool IdentifyNasProtoVersionToUse_STUB_SUCC(uint64_t &errCode)
{
    errCode = MP_SUCCESS;
    return true;
}

static bool CreateGeneralResource_Stub_SUC(void *ob, std::string key, HetroNativeGeneral &generalInfo)
{
    return true;
}

static bool CreateScanStatsResource_Stub_SUC(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return true;
}

static bool CreateBackupStatsResource_Stub_SUC(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return true;
}

static bool LockResource_Stub_SUC(std::string key)
{
    return true;
}

static bool UnlockResource_Stub_SUC(std::string key)
{
    return true;
}

static bool GetGeneralResource_Stub_SUC(void *ob, std::string key, HetroNativeGeneral &generalInfo)
{
    return true;
}

static bool GetScanStatsResource_Stub_SUC(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return true;
}

static bool GetBackupStatsResource_Stub_SUC(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return true;
}

static bool UpdateGeneralResource_Stub_SUC(void *ob, std::string key, HetroNativeGeneral &generalInfo)
{
    return true;
}

static bool UpdateScanStatsResource_Stub_SUC(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return true;
}

static bool UpdateBackupResource_Stub_SUC(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return true;
}

static bool DeleteGeneralResource_Stub_SUC(void *ob, std::string key)
{
    return true;
}

static bool DeleteScanStatsResource_Stub_SUC(void *ob, std::string key)
{
    return true;
}

static bool DeleteBackupStatsResource_Stub_SUC(void *ob, std::string key)
{
    return true;
}

static bool CreateGeneralResource_Stub_FAIL(void *ob, std::string key, HetroNativeGeneral &generalInfo)
{
    return false;
}

static bool CreateScanStatsResource_Stub_FAIL(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return false;
}

static bool CreateBackupStatsResource_Stub_FAIL(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return false;
}

static bool GetGeneralResource_Stub_FAIL(void *ob, std::string key, HetroNativeGeneral &generalInfo)
{
    return false;
}

static bool GetScanStatsResource_Stub_FAIL(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return false;
}

static bool GetBackupStatsResource_Stub_FAIL(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return false;
}

static bool UpdateGeneralResource_Stub_FAIL(void *ob, std::string key, HetroNativeGeneral &generalInfo)
{
    return false;
}

static bool UpdateScanStatsResource_Stub_FAIL(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return false;
}

static bool UpdateBackupResource_Stub_FAIL(void *ob, std::string key, HetroNativeScanStatistics &scanStats)
{
    return false;
}

static bool DeleteGeneralResource_Stub_FAIL(void *ob, std::string key)
{
    return false;
}

static bool DeleteScanStatsResource_Stub_FAIL(void *ob, std::string key)
{
    return false;
}

static bool DeleteBackupStatsResource_Stub_FAIL(void *ob, std::string key)
{
    return false;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_correct_val(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static void CheckCertThumbPrint_Stub_correct_val(void *obj, ActionResult& returnValue, const std::string& ip,
    const int32_t port, const std::string& thumbPrint)
{
    returnValue.code = MP_SUCCESS;
    return;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_format_protectEnv_extendInfo(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.protectEnv.extendInfo = "{\"snap\":true,\"verifyStatus\":\"1\",\"wwn\":\"\",}";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_format_protectObject_extendInfo(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.protectObject.extendInfo = "";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_format_backupJob_extendInfo(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.extendInfo = "xyz";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_repoCache_path(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    for (auto repo : backupJob.repositories) {
        if (repo.repositoryType == RepositoryDataType::CACHE_REPOSITORY) {
            string path = "/fakePath";
            repo.path.push_back(path);
        }
    }
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));

    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_dataCache_path(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    for (auto repo : backupJob.repositories) {
        if (repo.repositoryType == RepositoryDataType::DATA_REPOSITORY) {
            string path = "/fakePath";
            repo.path.push_back(path);
        }
    }
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_CIFS(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.protectObject.extendInfo = "{\"authMode\":\"1\",\"filters\":\"\",\"ip\":\"10.28.12.144\""
                                         ",\"kerberosId\":\"0\",\"shareMode\":\"0\"}";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_Incremental(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.jobParam.backupType = AppProtect::BackupJobType::INCREMENT_BACKUP;
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_UseSnapshot(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.protectEnv.extendInfo = "{\"snapConsistency\":true,\"verifyStatus\":\"1\",\"wwn\":\"\"}";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_protected_managementIP(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.protectEnv.endpoint = "10.28.12.xxx";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_protected_serviceIP(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.protectObject.extendInfo = "{\"authMode\":\"1\",\"filters\":\"\",\"ip\":\"10.28.12.xxx\""
                                         ",\"kerberosId\":\"0\",\"shareMode\":\"1\"}";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_protected_Sharepath(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.protectObject.name = "FakePathNotPresent";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_protected_Auth(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.protectObject.auth.authType = AuthType::APP_PASSWORD;
    backupJob.protectObject.auth.authkey = "admin";
    backupJob.protectObject.auth.authPwd = "Admin@123";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_format_jobParam_advanceParams(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.jobParam.advanceParams = "xyz";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_bad_format_jobParam_dataLayout_extendInfo(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.jobParam.dataLayout.extendInfo = "xyz";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_creation_time_filter(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.jobParam.filters[3].filterBy = "CreateTime";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static shared_ptr<JobCommonInfo> GetJobInfo_Stub_access_time_filter(void *obj)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    backupJob.jobParam.filters[3].filterBy = "AccessTime";
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    return jobInfo;
}

static int GetConfScanLibNfsOpenDirReqCnt_STUB(void *obj)
{
    return 4000;
}

static int GetConfBackupLibNfsFhCacheDisable_STUB(void *obj)
{
    return 0;
}

static int GetConfScanExtAclDirEnabled_STUB(void *obj)
{
    return 0;
}

static int GetConfScanExtAclFileEnabled_STUB(void *obj)
{
    return 0;
}

static int GetConfScanWriteTaskInstanceCnt_STUB(void *obj)
{
    return 1;
}

static int GetConfScanThreadPoolCnt_STUB(void *obj)
{
    return 32;
}

static int GetConfScanWriteTaskStartQueueSize_STUB(void *obj)
{
    return 1000;
}

static int GetConfScanWriteTaskStopQueueSize_STUB(void *obj)
{
    return 5000;
}

static int GetConfScanUseLastBackupTime_STUB(void *obj)
{
    return 1;
}

static int GetConfIsNasRestStub_STUB(void *obj)
{
    return 0;
}
static string GetConfScanCtrlMaxDataSize_STUB(void *obj)
{
    return "5368709120";
}
static int GetConfScanCtrlFileTimeSec_STUB(void *obj)
{
    return 5;
}
static int GetConfScanCtrlMaxEntriesFullBkup_STUB(void *obj)
{
    return 10000;
}
static int GetConfScanCtrlMaxEntriesIncBkup_STUB(void *obj)
{
    return 1000;
}
static int GetConfScanDefaultMetaFileSize_STUB(void *obj)
{
    return 1048576000;
}
static int GetConfScanLibnfsDirQPopSize_STUB(void *obj)
{
    return 20;
}
static int GetConfScanLibnfsReadDirQPopSize_STUB(void *obj)
{
    return 10;
}
static int GetConfScanMaxWriteQueueSize_STUB(void *obj)
{
    return 10000;
}

static int GetConfScanMinWriteQueueSize_STUB(void *obj)
{
    return 5000;
}

static bool InitJobInfo_STUB_FAIL(void *ob)
{
    return false;
}

static bool InitJobInfo_STUB_SUCC(void *ob)
{
    return true;
}

static bool StartScanner_STUB_Suc(void *ob)
{
    return true;
}

static void PushScanConfig_STUB(void *ob)
{
    return;
}

static bool WaitToStartScanner_STUB(void *ob)
{
    return true;
}

static void StubFunction_VOID(void *ob)
{}

static bool StubFunction_TRUE(void *ob)
{
    return true;
}

static bool MonitorScanner_STUB_Suc(void *ob, SCANNER_TASK_STATUS &scanTaskStatus,
    SubJobStatus::type &jobStatus, std::string &jobLogStr, int &jobProgress) 
{
    return true;
}

static void ReportJobDetails_Stub(void *ob, ActionResult& returnValue, const SubJobDetails& jobInfo)
{
    return;
}

static bool SnapshotNameResource_Stub(std::string key) {
    return true;
}

static bool CheckRemoteNasMount_Stub(std::string proto, std::string protoVersion,
    ProtectedNasShare &m_nasShare, std::string m_tempLocalMountPath)
{
    return true;
}

static bool CheckDataFsMount_Stub(std::string proto, std::string protoVersion,
    StorageRepository &m_dataFs, std::string m_dataFsSvcIp, ProtectedNasShare &m_nasShare)
{
    return true;
}
static void PrintFilterInfo_Stub()
{

}
static bool PrintJobInfo_Stub()
{
    return true;
}
static bool ReadBackupStatsFromFile_Stub(std::string filePath, HetroNativeBackupStats &backupStatistics)
{
    return true;
}
static bool RemoveDirectory_Stub_Succ(std::string path)
{
    return true;
}
static bool RemoveDir_Stub(const std::string &dirName)
{
    return true;
}
int KinitTGTInner_Stub(std::string userName, std::string password, std::string krb5Keytab,
    const std::string& krb5Conf, const std::string& uniqueFileJoinField)
{
    return Module::SUCCESS;

}

void PrintBackupCopyDebugInfo_Stub()
{
    return;
}

void FuzzHetroBackup::SetUp()
{
    m_hetroBackupJobObj = std::make_unique<HetroBackupJob>();
    SubJob subJob;
    subJob.__isset.subJobId = true;
    subJob.__set_jobId("sub_job_id");
    subJob.jobId = "jobId123";
    subJob.subJobId = "subJob123";
    subJob.jobName = "XYZ";
    subJob.jobPriority = 1;
    subJob.jobInfo = "{\"ControlFile\":\"\",\"SubTaskType\":1,\"Ext\":\"\"}";
    std::shared_ptr<SubJob> subJobptr = std::make_shared<SubJob>(subJob);
    m_hetroBackupJobObj->SetSubJob(subJobptr);

    stub.set(ADDR(JobService, ReportJobDetails), ReportJobDetails_Stub);
    stub.set(ADDR(HetroCommonService, CreateGeneralResource), CreateGeneralResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, CreateScanStatsResource), CreateScanStatsResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, CreateBackupStatsResource), CreateBackupStatsResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, LockResource), LockResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, UnlockResource), UnlockResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, GetGeneralResource), GetGeneralResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, GetScanStatsResource), GetScanStatsResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, GetBackupStatsResource), GetBackupStatsResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, UpdateGeneralResource), UpdateGeneralResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, UpdateScanStatsResource), UpdateScanStatsResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, UpdateBackupStatsResource), UpdateBackupResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, DeleteGeneralResource), DeleteGeneralResource_Stub_SUC);

    stub.set(ADDR(HetroCommonService, DeleteScanStatsResource), DeleteScanStatsResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, DeleteBackupStatsResource), DeleteBackupStatsResource_Stub_SUC);
    stub.set(ADDR(HetroCommonService, ReadBackupStatsFromFile), ReadBackupStatsFromFile_Stub);
    
    stub.set(ADDR(ScanMgr, CreateScanInst), CreateScanInst_Stub);
    stub.set(ADDR(SecurityService, CheckCertThumbPrint), CheckCertThumbPrint_Stub_correct_val);
    stub.set(ADDR(HetroBackupJob, PrintFilterInfo), PrintFilterInfo_Stub);
    stub.set(ADDR(HetroBackupJob, PrintJobInfo), PrintJobInfo_Stub);
    stub.set(ADDR(HetroBackupJob, PrintBackupCopyDebugInfo), PrintBackupCopyDebugInfo_Stub);
    
    stub.set(ADDR(PluginUtils, RemoveDirectory), RemoveDirectory_Stub_Succ);
    stub.set(ADDR(PluginUtils, RemoveDir), RemoveDir_Stub);
    stub.set(ADDR(PluginUtils, KinitTGTInner), KinitTGTInner_Stub);
    
    
    m_hetroBackupJobObj->m_cacheFsPath = "/MetaFS";
}

void FuzzHetroBackup::TearDown()
{
    stub.reset(ADDR(JobService, ReportJobDetails));
    stub.reset(ADDR(HetroCommonService, CreateGeneralResource));
    stub.reset(ADDR(HetroCommonService, CreateScanStatsResource));
    stub.reset(ADDR(HetroCommonService, CreateBackupStatsResource));
    stub.reset(ADDR(HetroCommonService, LockResource));
    stub.reset(ADDR(HetroCommonService, UnlockResource));
    stub.reset(ADDR(HetroCommonService, GetGeneralResource));
    stub.reset(ADDR(HetroCommonService, GetScanStatsResource));
    stub.reset(ADDR(HetroCommonService, GetBackupStatsResource));
    stub.reset(ADDR(HetroCommonService, UpdateGeneralResource));
    stub.reset(ADDR(HetroCommonService, UpdateScanStatsResource));
    stub.reset(ADDR(HetroCommonService, UpdateBackupStatsResource));
    stub.reset(ADDR(HetroCommonService, DeleteGeneralResource));
    stub.reset(ADDR(HetroCommonService, DeleteScanStatsResource));
    stub.reset(ADDR(HetroCommonService, DeleteBackupStatsResource));
    stub.reset(ADDR(ScanMgr, CreateScanInst));
    // stub.reset(ADDR(SecurityService, CheckCertThumbPrint));
    // stub.reset(ADDR(BasicJob, GetJobInfo));
    stub.reset(ADDR(HetroBackupJob, PrintFilterInfo));
    stub.reset(ADDR(HetroBackupJob, PrintJobInfo));
  
}

void FuzzHetroBackup::SetUpTestCase()
{
}

void FuzzHetroBackup::TearDownTestCase()
{
}

static bool UpdateScanStatsResource_Stub(std::string key, HetroNativeScanStatistics &scanStats)
{
    return true;
}

static void PrintSubJobInfo_Stub(std::shared_ptr<SubJob> &m_subJobInfo)
{
    return;
}

TEST_F(FuzzHetroBackup, PrerequisiteJob)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    m_hetroBackupJobObj->m_jobCommonInfo = jobInfo;
    stub.set(ADDR(HetroCommonService, CheckRemoteNasMount), CheckRemoteNasMount_Stub);
    stub.set(ADDR(HetroCommonService, CheckDataFsMount), CheckDataFsMount_Stub);
    m_hetroBackupJobObj->GetBackupJobInfo();
    DT_FUZZ_START(0, 100000,(char*)"FuzzHetroBackup_PrerequisiteJob" ,0)
    {
        char *remotePath = DT_SetGetString(&g_Element[0], 24, 1000 ,(char *)"/tmp/MetaFS/local/cache");
        m_hetroBackupJobObj->m_backupJobPtr->repositories[0].remotePath = remotePath;
        EXPECT_EQ(m_hetroBackupJobObj->PrerequisiteJob(), Module::SUCCESS);
    }
    DT_FUZZ_END()
    return;
}

TEST_F(FuzzHetroBackup, GenerateSubJob)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    m_hetroBackupJobObj->m_jobCommonInfo = jobInfo;
    m_hetroBackupJobObj->GetBackupJobInfo();
    DT_FUZZ_START(0, 100000,(char*)"FuzzHetroBackup_GenerateSubJob" ,0)
    {
        char *remotePath = DT_SetGetString(&g_Element[0], 24, 1000 ,(char *)"/tmp/MetaFS/local/cache");
        m_hetroBackupJobObj->m_backupJobPtr->repositories[0].remotePath = remotePath;
        m_hetroBackupJobObj->m_backupJobPtr->repositories[1].remotePath = remotePath;
        EXPECT_EQ(m_hetroBackupJobObj->GenerateSubJob(), Module::SUCCESS);
    }
    DT_FUZZ_END()    
}

TEST_F(FuzzHetroBackup, ExecuteSubJob)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    m_hetroBackupJobObj->m_jobCommonInfo = jobInfo;
    m_hetroBackupJobObj->GetBackupJobInfo();
    stub.set(ADDR(HetroCommonService, PrintSubJobInfo), PrintSubJobInfo_Stub);
    SubJob subJob;
    subJob.__isset.subJobId = true;
    subJob.__set_jobId("sub_job_id");
    subJob.jobId = "jobId123";
    subJob.subJobId = "subJob123";
    subJob.jobName = "XYZ";
    subJob.jobPriority = 1;
    DT_FUZZ_START(0, 100000,(char*)"FuzzHetroBackup_ExecuteSubJob" ,0)
    {
        char *ext = DT_SetGetString(&g_Element[0], 4, 1000, (char *)"abc");
        std::string extendValue = ext;
        std::replace(extendValue.begin(), extendValue.end(), '\\', '/');
        subJob.jobInfo.append("{\"ControlFile\":\"\",")
              .append("\"SubTaskType\":1,").append("\"Ext\":\"").append(extendValue)
              .append("\"}");
        std::shared_ptr<SubJob> subJobptr = std::make_shared<SubJob>(subJob);
        m_hetroBackupJobObj->SetSubJob(subJobptr);
        EXPECT_EQ(m_hetroBackupJobObj->ExecuteSubJob(), MP_SUCCESS);
    }
    DT_FUZZ_END()    
}

TEST_F(FuzzHetroBackup, PostJob)
{
    AppProtect::BackupJob backupJob = BackupJobSetup();
    std::shared_ptr<JobCommonInfo> jobInfo = make_shared<JobCommonInfo>(make_shared<BackupJob>(backupJob));
    m_hetroBackupJobObj->m_jobCommonInfo = jobInfo;
    m_hetroBackupJobObj->GetBackupJobInfo();
    DT_FUZZ_START(0, 100000,(char*)"FuzzHostBackup_PostJob" ,0)
    {
        char *remotePath = DT_SetGetString(&g_Element[0], 24, 1000 ,(char *)"/tmp/MetaFS/local/cache");
        m_hetroBackupJobObj->m_backupJobPtr->repositories[0].remotePath = remotePath;
        m_hetroBackupJobObj->m_backupJobPtr->repositories[1].remotePath = remotePath;
        EXPECT_EQ(m_hetroBackupJobObj->PostJob(), Module::SUCCESS);
    }
    DT_FUZZ_END()
}